/*
 * SvrSession.h
 *
 *  Created on: 2012-7-11
 *      Author: ThinkPad
 */

#ifndef SVRSESSION_H_
#define SVRSESSION_H_

#include "smart_lock.h"
#include "hash_link_table.h"
#include "link_list.h"
#include "utils.h"

static const int DEF_TIMEOUT = 120;            /*default time out,120 seconds*/
static const int MAX_CONNTIME = 36000;         /*max session duration 10 hours*/

/*
* sessoin auth status
*/
enum AUTH_STATUS{AUTH_INIT,AUTH_WAIT,AUTH_DISCONN_WAIT,AUTH_SUCCESS,AUTH_FAILURE};
enum SESSION_OP_MARK{NORMAL,SCLOSE};
/*
*client session node
*/
#pragma pack()
struct session_node
{
        uint16_t id;/*content id ,channel id,live id and so on!*/
        uint32_t client_ip;/*client ip address*/
        uint32_t connid;/*conn id*/
        uint64_t total_trans_size;/*total trans size bytes*/
        char     certificate[CERTIFICATE_LEN];/*certificate data*/
        char     request_content[FILE_MAX_PATH];/*request conetent name*/
        long     request_content_hash_index; /*request conetent name hash index*/
        bool     conn_status;   /*current connection status*/
        AUTH_STATUS     iauthcode;
        SESSION_OP_MARK op_flag;	/*op flag*/
        time_t   connection_time;/*begin connection time*/
        time_t   last_conn_time;/*last connection time*/
        uint16_t conn_count;/*request count*/
        /*net connection  index*/
        u_long   conn_index;
        /*node du-link list ptr*/
        session_node *prev,*next;
        /*node hash table du2-link list ptr*/
        char  key[GUID_LEN];
        long  key_index;/*object hash key*/
        session_node *hash_prev,*hash_next;
        /*init*/
        session_node()
        {
            key_index = 0;
            last_conn_time = time_t(_NULL);
            connection_time = time_t(NULL);
            total_trans_size = 0;

            memset(key,'\0',sizeof(key));
            memset(certificate,'\0',CERTIFICATE_LEN);
            memset(request_content,'\0',FILE_MAX_PATH);
            request_content_hash_index = 0;

            conn_status = false;
            conn_count = 0;
            op_flag = NORMAL;
            iauthcode = AUTH_INIT;
            client_ip = 0;
            id = 0;
            conn_index = 0;

            prev = _NULL;
            next = _NULL;

            hash_prev= _NULL;
            hash_next= _NULL;
        }
};


class SvrSession
{
public:
        SvrSession(void);
        ~SvrSession(void);

        /*init session class*/
        int init(int init_size = DFLT_MIN_CONN_SIZ);

        /*
        *add_session
        *false ʧ��,and auto free node
        */
        bool add_session(session_node * s);
        /*
        *find_session
        *0:�ɹ�
        */
        session_node* find_session(const char * key);
        /*
        *find_session auth_status
        */
        AUTH_STATUS find_session_auth_status(const char * key);

        /*
        *find_session id
        */
        uint16_t find_session_id(const char * key);
        /*
        *find_session net conn index,>0:success
        */
        u_long find_session_net_conn_index(const char * key);
        /*
        *set auth_status
        */
        bool set_session_auth_status(const char * key,AUTH_STATUS status);
        /*
        *set session active status
        */
        bool set_session_active_status(const char * key,bool isalive,uint64_t trans_size = 0);

        /*
        *set session heartbeat
        */
        bool set_session_heartbeat(const char * key);
        /*
        *remove_session
        */
        int remove_session(const char * key);

        /*
        *session resource pool alloc
        */
        int alloc_node(session_node ** s);
        /*
        *session resource pool free
        */
        int free_node(session_node * s);
        /*
        *session resource count
        */
        int get_session_count();
        int get_free_session_count();
        /*
        *use it must be carefull
        *session_list_lock, lock do enter call,
        *when you usr completed,then call end_enter
        */
        session_node * begin_enter(void);
        void end_enter(void);
private:
        /*session hash table list,only for find quick*/
        hash_link_table<session_node> session_table;
        link_list<session_node> session_list;
        smart_lock  session_list_lock;
        bool        lock_flag;
        int 		DEF_SESSION_POOL_SIZE;  /*init default size svr_session object*/

        /*free list*/
        link_list<session_node> free_list;
        smart_lock  free_list_lock;
};

#endif /* SVRSESSION_H_ */
